home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / vidhrdw / pipedrm.c < prev    next >
C/C++ Source or Header  |  2000-05-21  |  12KB  |  463 lines

  1. /***************************************************************************
  2.  
  3.   vidhrdw/pipedrm.c
  4.  
  5.   Functions to emulate the video hardware of the machine.
  6.  
  7. ****************************************************************************/
  8.  
  9. #include "driver.h"
  10. #include "vidhrdw/generic.h"
  11.  
  12.  
  13. /*************************************
  14.  *
  15.  *    Statics
  16.  *
  17.  *************************************/
  18.  
  19. extern UINT8 pipedrm_video_control;
  20.  
  21. static struct osd_bitmap *background[2];
  22. static UINT8 *background_dirty[2];
  23. static UINT8 *local_videoram[2];
  24.  
  25. static UINT8 scroll_regs[4];
  26.  
  27.  
  28.  
  29. /*************************************
  30.  *
  31.  *    Prototypes
  32.  *
  33.  *************************************/
  34.  
  35. void pipedrm_vh_stop(void);
  36.  
  37.  
  38.  
  39. /*************************************
  40.  *
  41.  *    Video system start
  42.  *
  43.  *************************************/
  44.  
  45. int pipedrm_vh_start(void)
  46. {
  47.     /* allocate videoram */
  48.     local_videoram[0] = malloc(videoram_size);
  49.     local_videoram[1] = malloc(videoram_size);
  50.  
  51.     /* allocate background bitmaps */
  52.     background[0] = osd_new_bitmap(64*8, 64*4, Machine->scrbitmap->depth);
  53.     background[1] = osd_new_bitmap(64*8, 64*4, Machine->scrbitmap->depth);
  54.  
  55.     /* allocate dirty buffers */
  56.     background_dirty[0] = malloc(64*64);
  57.     background_dirty[1] = malloc(64*64);
  58.  
  59.     /* handle errors */
  60.     if (!local_videoram[0] || !local_videoram[1] || !background[0] || !background[1] || !background_dirty[0] || !background_dirty[1])
  61.     {
  62.         pipedrm_vh_stop();
  63.         return 1;
  64.     }
  65.  
  66.     /* reset the system */
  67.     memset(background_dirty[0], 1, 64*64);
  68.     memset(background_dirty[1], 1, 64*64);
  69.     return 0;
  70. }
  71.  
  72.  
  73.  
  74. /*************************************
  75.  *
  76.  *    Video system shutdown
  77.  *
  78.  *************************************/
  79.  
  80. void pipedrm_vh_stop(void)
  81. {
  82.     /* free the dirty buffers */
  83.     if (background_dirty[1])
  84.         free(background_dirty[1]);
  85.     background_dirty[1] = NULL;
  86.  
  87.     if (background_dirty[0])
  88.         free(background_dirty[0]);
  89.     background_dirty[0] = NULL;
  90.  
  91.     /* free the background bitmaps */
  92.     if (background[1])
  93.         osd_free_bitmap(background[1]);
  94.     background[1] = NULL;
  95.  
  96.     if (background[0])
  97.         osd_free_bitmap(background[0]);
  98.     background[0] = NULL;
  99.  
  100.     /* free videoram */
  101.     if (local_videoram[1])
  102.         free(local_videoram[1]);
  103.     local_videoram[1] = NULL;
  104.  
  105.     if (local_videoram[0])
  106.         free(local_videoram[0]);
  107.     local_videoram[0] = NULL;
  108. }
  109.  
  110.  
  111.  
  112. /*************************************
  113.  *
  114.  *        Write handlers
  115.  *
  116.  *************************************/
  117.  
  118. WRITE_HANDLER( pipedrm_videoram_w )
  119. {
  120.     int which = (pipedrm_video_control >> 3) & 1;
  121.     if (local_videoram[which][offset] != data)
  122.     {
  123.         local_videoram[which][offset] = data;
  124.         background_dirty[which][offset & 0xfff] = 1;
  125.     }
  126. }
  127.  
  128.  
  129. WRITE_HANDLER( hatris_videoram_w )
  130. {
  131.     int which = (~pipedrm_video_control >> 1) & 1;
  132.     if (local_videoram[which][offset] != data)
  133.     {
  134.         local_videoram[which][offset] = data;
  135.         background_dirty[which][offset & 0xfff] = 1;
  136.     }
  137. }
  138.  
  139.  
  140. WRITE_HANDLER( pipedrm_scroll_regs_w )
  141. {
  142.     scroll_regs[offset] = data;
  143. }
  144.  
  145.  
  146. READ_HANDLER( pipedrm_videoram_r )
  147. {
  148.     int which = (pipedrm_video_control >> 3) & 1;
  149.     return local_videoram[which][offset];
  150. }
  151.  
  152.  
  153. READ_HANDLER( hatris_videoram_r )
  154. {
  155.     int which = (~pipedrm_video_control >> 1) & 1;
  156.     return local_videoram[which][offset];
  157. }
  158.  
  159.  
  160.  
  161. /*************************************
  162.  *
  163.  *        Palette marking
  164.  *
  165.  *************************************/
  166.  
  167. static void mark_background_colors(void)
  168. {
  169.     int mask1 = Machine->gfx[0]->total_elements - 1;
  170.     int mask2 = Machine->gfx[1]->total_elements - 1;
  171.     int colormask = Machine->gfx[0]->total_colors - 1;
  172.     UINT16 used_colors[128];
  173.     int code, color, offs;
  174.  
  175.     /* reset all color codes */
  176.     memset(used_colors, 0, sizeof(used_colors));
  177.  
  178.     /* loop over tiles */
  179.     for (offs = 0; offs < 64*64; offs++)
  180.     {
  181.         /* consider background 0 */
  182.         color = local_videoram[0][offs] & colormask;
  183.         code = (local_videoram[0][offs + 0x1000] << 8) | local_videoram[0][offs + 0x2000];
  184.         used_colors[color] |= Machine->gfx[0]->pen_usage[code & mask1];
  185.  
  186.         /* consider background 1 */
  187.         color = local_videoram[1][offs] & colormask;
  188.         code = (local_videoram[1][offs + 0x1000] << 8) | local_videoram[1][offs + 0x2000];
  189.         used_colors[color] |= Machine->gfx[1]->pen_usage[code & mask2] & 0x7fff;
  190.     }
  191.  
  192.     /* fill in the final table */
  193.     for (offs = 0; offs <= colormask; offs++)
  194.     {
  195.         UINT16 used = used_colors[offs];
  196.         if (used)
  197.         {
  198.             for (color = 0; color < 15; color++)
  199.                 if (used & (1 << color))
  200.                     palette_used_colors[offs * 16 + color] = PALETTE_COLOR_USED;
  201.             if (used & 0x8000)
  202.                 palette_used_colors[offs * 16 + 15] = PALETTE_COLOR_USED;
  203.             else
  204.                 palette_used_colors[offs * 16 + 15] = PALETTE_COLOR_TRANSPARENT;
  205.         }
  206.     }
  207. }
  208.  
  209.  
  210. static void mark_sprite_palette(void)
  211. {
  212.     UINT16 used_colors[0x20];
  213.     int offs, i;
  214.  
  215.     /* clear the color array */
  216.     memset(used_colors, 0, sizeof(used_colors));
  217.  
  218.     /* find the used sprites */
  219.     for (offs = 0; offs < spriteram_size; offs += 8)
  220.     {
  221.         int data2 = spriteram[offs + 4] | (spriteram[offs + 5] << 8);
  222.  
  223.         /* turns out the sprites are the same as in aerofgt.c */
  224.         if (data2 & 0x80)
  225.         {
  226.             int data3 = spriteram[offs + 6] | (spriteram[offs + 7] << 8);
  227.             int code = data3 & 0xfff;
  228.             int color = data2 & 0x0f;
  229.             int xtiles = ((data2 >> 8) & 7) + 1;
  230.             int ytiles = ((data2 >> 12) & 7) + 1;
  231.             int tiles = xtiles * ytiles;
  232.             int t;
  233.  
  234.             /* normal case */
  235.             for (t = 0; t < tiles; t++)
  236.                 used_colors[color] |= Machine->gfx[2]->pen_usage[code++];
  237.         }
  238.     }
  239.  
  240.     /* now mark the pens */
  241.     for (offs = 0; offs < 0x20; offs++)
  242.     {
  243.         UINT16 used = used_colors[offs];
  244.         if (used)
  245.         {
  246.             for (i = 0; i < 15; i++)
  247.                 if (used & (1 << i))
  248.                     palette_used_colors[1024 + offs * 16 + i] = PALETTE_COLOR_USED;
  249.             palette_used_colors[1024 + offs * 16 + 15] = PALETTE_COLOR_TRANSPARENT;
  250.         }
  251.     }
  252. }
  253.  
  254.  
  255.  
  256. /*************************************
  257.  *
  258.  *        Sprite routines
  259.  *
  260.  *************************************/
  261.  
  262. static void draw_sprites(struct osd_bitmap *bitmap, int draw_priority)
  263. {
  264.     UINT8 zoomtable[16] = { 0,7,14,20,25,30,34,38,42,46,49,52,54,57,59,61 };
  265.     int offs;
  266.  
  267.     /* draw the sprites */
  268.     for (offs = 0; offs < spriteram_size; offs += 8)
  269.     {
  270.         int data2 = spriteram[offs + 4] | (spriteram[offs + 5] << 8);
  271.         int priority = (data2 >> 4) & 1;
  272.  
  273.         /* turns out the sprites are the same as in aerofgt.c */
  274.         if ((data2 & 0x80) && priority == draw_priority)
  275.         {
  276.             int data0 = spriteram[offs + 0] | (spriteram[offs + 1] << 8);
  277.             int data1 = spriteram[offs + 2] | (spriteram[offs + 3] << 8);
  278.             int data3 = spriteram[offs + 6] | (spriteram[offs + 7] << 8);
  279.             int code = data3 & 0xfff;
  280.             int color = data2 & 0x0f;
  281.             int y = (data0 & 0x1ff) - 6;
  282.             int x = (data1 & 0x1ff) - 13;
  283.             int yzoom = (data0 >> 12) & 15;
  284.             int xzoom = (data1 >> 12) & 15;
  285.             int zoomed = (xzoom | yzoom);
  286.             int ytiles = ((data2 >> 12) & 7) + 1;
  287.             int xtiles = ((data2 >> 8) & 7) + 1;
  288.             int yflip = (data2 >> 15) & 1;
  289.             int xflip = (data2 >> 11) & 1;
  290.             int xt, yt;
  291.  
  292.             /* compute the zoom factor -- stolen from aerofgt.c */
  293.             xzoom = 16 - zoomtable[xzoom] / 8;
  294.             yzoom = 16 - zoomtable[yzoom] / 8;
  295.  
  296.             /* wrap around */
  297.             if (x > Machine->drv->visible_area.max_x) x -= 0x200;
  298.             if (y > Machine->drv->visible_area.max_y) y -= 0x200;
  299.  
  300.             /* normal case */
  301.             if (!xflip && !yflip)
  302.             {
  303.                 for (yt = 0; yt < ytiles; yt++)
  304.                     for (xt = 0; xt < xtiles; xt++, code++)
  305.                         if (!zoomed)
  306.                             drawgfx(bitmap, Machine->gfx[2], code, color, 0, 0,
  307.                                     x + xt * 16, y + yt * 16, 0, TRANSPARENCY_PEN, 15);
  308.                         else
  309.                             drawgfxzoom(bitmap, Machine->gfx[2], code, color, 0, 0,
  310.                                     x + xt * xzoom, y + yt * yzoom, 0, TRANSPARENCY_PEN, 15,
  311.                                     0x1000 * xzoom, 0x1000 * yzoom);
  312.             }
  313.  
  314.             /* xflipped case */
  315.             else if (xflip && !yflip)
  316.             {
  317.                 for (yt = 0; yt < ytiles; yt++)
  318.                     for (xt = 0; xt < xtiles; xt++, code++)
  319.                         if (!zoomed)
  320.                             drawgfx(bitmap, Machine->gfx[2], code, color, 1, 0,
  321.                                     x + (xtiles - 1 - xt) * 16, y + yt * 16, 0, TRANSPARENCY_PEN, 15);
  322.                         else
  323.                             drawgfxzoom(bitmap, Machine->gfx[2], code, color, 1, 0,
  324.                                     x + (xtiles - 1 - xt) * xzoom, y + yt * yzoom, 0, TRANSPARENCY_PEN, 15,
  325.                                     0x1000 * xzoom, 0x1000 * yzoom);
  326.             }
  327.  
  328.             /* yflipped case */
  329.             else if (!xflip && yflip)
  330.             {
  331.                 for (yt = 0; yt < ytiles; yt++)
  332.                     for (xt = 0; xt < xtiles; xt++, code++)
  333.                         if (!zoomed)
  334.                             drawgfx(bitmap, Machine->gfx[2], code, color, 0, 1,
  335.                                     x + xt * 16, y + (ytiles - 1 - yt) * 16, 0, TRANSPARENCY_PEN, 15);
  336.                         else
  337.                             drawgfxzoom(bitmap, Machine->gfx[2], code, color, 0, 1,
  338.                                     x + xt * xzoom, y + (ytiles - 1 - yt) * yzoom, 0, TRANSPARENCY_PEN, 15,
  339.                                     0x1000 * xzoom, 0x1000 * yzoom);
  340.             }
  341.  
  342.             /* x & yflipped case */
  343.             else
  344.             {
  345.                 for (yt = 0; yt < ytiles; yt++)
  346.                     for (xt = 0; xt < xtiles; xt++, code++)
  347.                         if (!zoomed)
  348.                             drawgfx(bitmap, Machine->gfx[2], code, color, 1, 1,
  349.                                     x + (xtiles - 1 - xt) * 16, y + (ytiles - 1 - yt) * 16, 0, TRANSPARENCY_PEN, 15);
  350.                         else
  351.                             drawgfxzoom(bitmap, Machine->gfx[2], code, color, 1, 1,
  352.                                     x + (xtiles - 1 - xt) * xzoom, y + (ytiles - 1 - yt) * yzoom, 0, TRANSPARENCY_PEN, 15,
  353.                                     0x1000 * xzoom, 0x1000 * yzoom);
  354.             }
  355.         }
  356.     }
  357. }
  358.  
  359.  
  360. /*************************************
  361.  *
  362.  *        Main screen refresh
  363.  *
  364.  *************************************/
  365.  
  366. static void common_screenrefresh(int full_refresh)
  367. {
  368.     UINT16 saved_pens[64];
  369.     int offs;
  370.  
  371.     /* update the palette usage */
  372.     palette_init_used_colors();
  373.     mark_background_colors();
  374.     if (Machine->gfx[2])
  375.         mark_sprite_palette();
  376.  
  377.     /* handle full refresh */
  378.     if (palette_recalc() || full_refresh)
  379.     {
  380.         memset(background_dirty[0], 1, 64*64);
  381.         memset(background_dirty[1], 1, 64*64);
  382.     }
  383.  
  384.     /* update background 1 (opaque) */
  385.     for (offs = 0; offs < 64*64; offs++)
  386.         if (background_dirty[0][offs])
  387.         {
  388.             int color = local_videoram[0][offs];
  389.             int code = (local_videoram[0][offs + 0x1000] << 8) | local_videoram[0][offs + 0x2000];
  390.             int sx = offs % 64;
  391.             int sy = offs / 64;
  392.             drawgfx(background[0], Machine->gfx[0], code, color, 0, 0, sx * 8, sy * 4, 0, TRANSPARENCY_NONE, 0);
  393.             background_dirty[0][offs] = 0;
  394.         }
  395.  
  396.     /* mark the transparent pens transparent before drawing to background 2 */
  397.     for (offs = 0; offs < 64; offs++)
  398.     {
  399.         saved_pens[offs] = Machine->gfx[0]->colortable[offs * 16 + 15];
  400.         Machine->gfx[0]->colortable[offs * 16 + 15] = palette_transparent_pen;
  401.     }
  402.  
  403.     /* update background 2 (transparent) */
  404.     for (offs = 0; offs < 64*64; offs++)
  405.         if (background_dirty[1][offs])
  406.         {
  407.             int color = local_videoram[1][offs];
  408.             int code = (local_videoram[1][offs + 0x1000] << 8) | local_videoram[1][offs + 0x2000];
  409.             int sx = offs % 64;
  410.             int sy = offs / 64;
  411.             drawgfx(background[1], Machine->gfx[1], code, color, 0, 0, sx * 8, sy * 4, 0, TRANSPARENCY_NONE, 0);
  412.             background_dirty[1][offs] = 0;
  413.         }
  414.  
  415.     /* restore the saved pens */
  416.     for (offs = 0; offs < 64; offs++)
  417.         Machine->gfx[0]->colortable[offs * 16 + 15] = saved_pens[offs];
  418.  
  419. }
  420.  
  421.  
  422. void pipedrm_vh_screenrefresh(struct osd_bitmap *bitmap, int full_refresh)
  423. {
  424.     int x, y;
  425.  
  426.     common_screenrefresh(full_refresh);
  427.  
  428.     /* draw the lower background */
  429.     x = 0;
  430.     y = -scroll_regs[1] - 7;
  431.     copyscrollbitmap(bitmap, background[0], 1, &x, 1, &y, &Machine->drv->visible_area, TRANSPARENCY_NONE, 0);
  432.  
  433.     /* draw the upper background */
  434.     x = 0;
  435.     y = -scroll_regs[3] - 7;
  436.     copyscrollbitmap(bitmap, background[1], 1, &x, 1, &y, &Machine->drv->visible_area, TRANSPARENCY_PEN, palette_transparent_pen);
  437.  
  438.     /* draw all the sprites (priority doesn't seem to matter) */
  439.     if (Machine->gfx[2])
  440.     {
  441.         draw_sprites(bitmap, 0);
  442.         draw_sprites(bitmap, 1);
  443.     }
  444. }
  445.  
  446.  
  447. void hatris_vh_screenrefresh(struct osd_bitmap *bitmap, int full_refresh)
  448. {
  449.     int x, y;
  450.  
  451.     common_screenrefresh(full_refresh);
  452.  
  453.     /* draw the lower background */
  454.     x = 0;
  455.     y = -scroll_regs[3] - 7;
  456.     copyscrollbitmap(bitmap, background[0], 1, &x, 1, &y, &Machine->drv->visible_area, TRANSPARENCY_NONE, 0);
  457.  
  458.     /* draw the upper background */
  459.     x = 0;
  460.     y = -scroll_regs[1] - 7;
  461.     copyscrollbitmap(bitmap, background[1], 1, &x, 1, &y, &Machine->drv->visible_area, TRANSPARENCY_PEN, palette_transparent_pen);
  462. }
  463.